// 字库芯片GT23L16U2W的地址计算
// superzlc
// 20180414112525

#ifndef __GT23L16U2W_ADDR_H_
#define __GT23L16U2W_ADDR_H_ 1

#include <avr/pgmspace.h>

// 按照 WORD 方式进行排列的字符对应表
const prog_int16_t zf_table_by_word[1088] = {
	0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,
	0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,
	0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,
	0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,
	0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,
	0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,
	0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,
	0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,0xe0,
	0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,
	0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,
	0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
	0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,0x101,
	0x113,0x11b,0x12b,0x144,0x148,0x14d,0x152,0x153,
	0x160,0x161,0x16b,0x178,0x192,0x1ce,0x1d0,0x1d2,
	0x1d4,0x1d6,0x1d8,0x1da,0x1dc,0x251,0x261,0x2c6,
	0x2c7,0x2c9,0x2ca,0x2cb,0x2d9,0x2dc,0x391,0x392,
	0x393,0x394,0x395,0x396,0x397,0x398,0x399,0x39a,
	0x39b,0x39c,0x39d,0x39e,0x39f,0x3a0,0x3a1,0x3a3,
	0x3a4,0x3a5,0x3a6,0x3a7,0x3a8,0x3a9,0x3b1,0x3b2,
	0x3b3,0x3b4,0x3b5,0x3b6,0x3b7,0x3b8,0x3b9,0x3ba,
	0x3bb,0x3bc,0x3bd,0x3be,0x3bf,0x3c0,0x3c1,0x3c3,
	0x3c4,0x3c5,0x3c6,0x3c7,0x3c8,0x3c9,0x401,0x410,
	0x411,0x412,0x413,0x414,0x415,0x416,0x417,0x418,
	0x419,0x41a,0x41b,0x41c,0x41d,0x41e,0x41f,0x420,
	0x421,0x422,0x423,0x424,0x425,0x426,0x427,0x428,
	0x429,0x42a,0x42b,0x42c,0x42d,0x42e,0x42f,0x430,
	0x431,0x432,0x433,0x434,0x435,0x436,0x437,0x438,
	0x439,0x43a,0x43b,0x43c,0x43d,0x43e,0x43f,0x440,
	0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,
	0x449,0x44a,0x44b,0x44c,0x44d,0x44e,0x44f,0x451,
	0x2010,0x2013,0x2014,0x2015,0x2016,0x2018,0x2019,0x201a,
	0x201c,0x201d,0x201e,0x2020,0x2021,0x2022,0x2025,0x2026,
	0x2030,0x2032,0x2033,0x2035,0x2039,0x203a,0x203b,0x20ac,
	0x2103,0x2105,0x2109,0x2116,0x2121,0x2122,0x2160,0x2161,
	0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,
	0x216a,0x216b,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,
	0x2176,0x2177,0x2178,0x2179,0x2190,0x2191,0x2192,0x2193,
	0x2196,0x2197,0x2198,0x2199,0x2208,0x220f,0x2211,0x2215,
	0x221a,0x221d,0x221e,0x221f,0x2220,0x2223,0x2225,0x2227,
	0x2228,0x2229,0x222a,0x222b,0x222e,0x2234,0x2235,0x2236,
	0x2237,0x223d,0x2248,0x224c,0x2252,0x2260,0x2261,0x2264,
	0x2265,0x2266,0x2267,0x226e,0x226f,0x2295,0x2299,0x22a5,
	0x22bf,0x2312,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,
	0x2466,0x2467,0x2468,0x2469,0x2474,0x2475,0x2476,0x2477,
	0x2478,0x2479,0x247a,0x247b,0x247c,0x247d,0x247e,0x247f,
	0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487,
	0x2488,0x2489,0x248a,0x248b,0x248c,0x248d,0x248e,0x248f,
	0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497,
	0x2498,0x2499,0x249a,0x249b,0x2500,0x2501,0x2502,0x2503,
	0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250a,0x250b,
	0x250c,0x250d,0x250e,0x250f,0x2510,0x2511,0x2512,0x2513,
	0x2514,0x2515,0x2516,0x2517,0x2518,0x2519,0x251a,0x251b,
	0x251c,0x251d,0x251e,0x251f,0x2520,0x2521,0x2522,0x2523,
	0x2524,0x2525,0x2526,0x2527,0x2528,0x2529,0x252a,0x252b,
	0x252c,0x252d,0x252e,0x252f,0x2530,0x2531,0x2532,0x2533,
	0x2534,0x2535,0x2536,0x2537,0x2538,0x2539,0x253a,0x253b,
	0x253c,0x253d,0x253e,0x253f,0x2540,0x2541,0x2542,0x2543,
	0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254a,0x254b,
	0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,
	0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,0x255f,
	0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,
	0x2568,0x2569,0x256a,0x256b,0x256c,0x256d,0x256e,0x256f,
	0x2570,0x2571,0x2572,0x2573,0x2581,0x2582,0x2583,0x2584,
	0x2585,0x2586,0x2587,0x2588,0x2589,0x258a,0x258b,0x258c,
	0x258d,0x258e,0x258f,0x2593,0x2594,0x2595,0x25a0,0x25a1,
	0x25b2,0x25b3,0x25bc,0x25bd,0x25c6,0x25c7,0x25cb,0x25ce,
	0x25cf,0x25e2,0x25e3,0x25e4,0x25e5,0x2605,0x2606,0x2609,
	0x2640,0x2642,0x3000,0x3001,0x3002,0x3003,0x3005,0x3006,
	0x3007,0x3008,0x3009,0x300a,0x300b,0x300c,0x300d,0x300e,
	0x300f,0x3010,0x3011,0x3012,0x3013,0x3014,0x3015,0x3016,
	0x3017,0x301d,0x301e,0x3021,0x3022,0x3023,0x3024,0x3025,
	0x3026,0x3027,0x3028,0x3029,0x303e,0x3041,0x3042,0x3043,
	0x3044,0x3045,0x3046,0x3047,0x3048,0x3049,0x304a,0x304b,
	0x304c,0x304d,0x304e,0x304f,0x3050,0x3051,0x3052,0x3053,
	0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305a,0x305b,
	0x305c,0x305d,0x305e,0x305f,0x3060,0x3061,0x3062,0x3063,
	0x3064,0x3065,0x3066,0x3067,0x3068,0x3069,0x306a,0x306b,
	0x306c,0x306d,0x306e,0x306f,0x3070,0x3071,0x3072,0x3073,
	0x3074,0x3075,0x3076,0x3077,0x3078,0x3079,0x307a,0x307b,
	0x307c,0x307d,0x307e,0x307f,0x3080,0x3081,0x3082,0x3083,
	0x3084,0x3085,0x3086,0x3087,0x3088,0x3089,0x308a,0x308b,
	0x308c,0x308d,0x308e,0x308f,0x3090,0x3091,0x3092,0x3093,
	0x309b,0x309c,0x309d,0x309e,0x30a1,0x30a2,0x30a3,0x30a4,
	0x30a5,0x30a6,0x30a7,0x30a8,0x30a9,0x30aa,0x30ab,0x30ac,
	0x30ad,0x30ae,0x30af,0x30b0,0x30b1,0x30b2,0x30b3,0x30b4,
	0x30b5,0x30b6,0x30b7,0x30b8,0x30b9,0x30ba,0x30bb,0x30bc,
	0x30bd,0x30be,0x30bf,0x30c0,0x30c1,0x30c2,0x30c3,0x30c4,
	0x30c5,0x30c6,0x30c7,0x30c8,0x30c9,0x30ca,0x30cb,0x30cc,
	0x30cd,0x30ce,0x30cf,0x30d0,0x30d1,0x30d2,0x30d3,0x30d4,
	0x30d5,0x30d6,0x30d7,0x30d8,0x30d9,0x30da,0x30db,0x30dc,
	0x30dd,0x30de,0x30df,0x30e0,0x30e1,0x30e2,0x30e3,0x30e4,
	0x30e5,0x30e6,0x30e7,0x30e8,0x30e9,0x30ea,0x30eb,0x30ec,
	0x30ed,0x30ee,0x30ef,0x30f0,0x30f1,0x30f2,0x30f3,0x30f4,
	0x30f5,0x30f6,0x30fc,0x30fd,0x30fe,0x3105,0x3106,0x3107,
	0x3108,0x3109,0x310a,0x310b,0x310c,0x310d,0x310e,0x310f,
	0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,
	0x3118,0x3119,0x311a,0x311b,0x311c,0x311d,0x311e,0x311f,
	0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127,
	0x3128,0x3129,0x3220,0x3221,0x3222,0x3223,0x3224,0x3225,
	0x3226,0x3227,0x3228,0x3229,0x3231,0x32a3,0x338e,0x338f,
	0x339c,0x339d,0x339e,0x33a1,0x33c4,0x33ce,0x33d1,0x33d2,
	0x33d5,0xe76c,0xe78d,0xe78e,0xe78f,0xe790,0xe791,0xe792,
	0xe793,0xe794,0xe795,0xe796,0xe7c7,0xe7c8,0xe7e7,0xe7e8,
	0xe7e9,0xe7ea,0xe7eb,0xe7ec,0xe7ed,0xe7ee,0xe7ef,0xe7f0,
	0xe7f1,0xe7f2,0xe7f3,0xe815,0xe816,0xe817,0xe818,0xe819,
	0xe81a,0xe81b,0xe81c,0xe81d,0xe81e,0xe81f,0xe820,0xe821,
	0xe822,0xe823,0xe824,0xe825,0xe826,0xe827,0xe828,0xe829,
	0xe82a,0xe82b,0xe82c,0xe82d,0xe82e,0xe82f,0xe830,0xe831,
	0xe832,0xe833,0xe834,0xe835,0xe836,0xe837,0xe838,0xe839,
	0xe83a,0xe83b,0xe83c,0xe83d,0xe83e,0xe83f,0xe840,0xe841,
	0xe842,0xe843,0xe844,0xe845,0xe846,0xe847,0xe848,0xe849,
	0xe84a,0xe84b,0xe84c,0xe84d,0xe84e,0xe84f,0xe850,0xe851,
	0xe852,0xe853,0xe854,0xe855,0xe856,0xe857,0xe858,0xe859,
	0xe85a,0xe85b,0xe85c,0xe85d,0xe85e,0xe85f,0xe860,0xe861,
	0xe862,0xe863,0xe864,0xf92c,0xf979,0xf995,0xf9e7,0xf9f1,
	0xfa0c,0xfa0d,0xfa0e,0xfa0f,0xfa11,0xfa13,0xfa14,0xfa18,
	0xfa1f,0xfa20,0xfa21,0xfa23,0xfa24,0xfa27,0xfa28,0xfa29,
	0xfe30,0xfe31,0xfe33,0xfe34,0xfe35,0xfe36,0xfe37,0xfe38,
	0xfe39,0xfe3a,0xfe3b,0xfe3c,0xfe3d,0xfe3e,0xfe3f,0xfe40,
	0xfe41,0xfe42,0xfe43,0xfe44,0xfe49,0xfe4a,0xfe4b,0xfe4c,
	0xfe4d,0xfe4e,0xfe4f,0xfe50,0xfe51,0xfe52,0xfe54,0xfe55,
	0xfe56,0xfe57,0xfe59,0xfe5a,0xfe5b,0xfe5c,0xfe5d,0xfe5e,
	0xfe5f,0xfe60,0xfe61,0xfe62,0xfe63,0xfe64,0xfe65,0xfe66,
	0xfe68,0xfe69,0xfe6a,0xfe6b,0xff01,0xff02,0xff03,0xff04,
	0xff05,0xff06,0xff07,0xff08,0xff09,0xff0a,0xff0b,0xff0c,
	0xff0d,0xff0e,0xff0f,0xff10,0xff11,0xff12,0xff13,0xff14,
	0xff15,0xff16,0xff17,0xff18,0xff19,0xff1a,0xff1b,0xff1c,
	0xff1d,0xff1e,0xff1f,0xff20,0xff21,0xff22,0xff23,0xff24,
	0xff25,0xff26,0xff27,0xff28,0xff29,0xff2a,0xff2b,0xff2c,
	0xff2d,0xff2e,0xff2f,0xff30,0xff31,0xff32,0xff33,0xff34,
	0xff35,0xff36,0xff37,0xff38,0xff39,0xff3a,0xff3b,0xff3c,
	0xff3d,0xff3e,0xff3f,0xff40,0xff41,0xff42,0xff43,0xff44,
	0xff45,0xff46,0xff47,0xff48,0xff49,0xff4a,0xff4b,0xff4c,
	0xff4d,0xff4e,0xff4f,0xff50,0xff51,0xff52,0xff53,0xff54,
	0xff55,0xff56,0xff57,0xff58,0xff59,0xff5a,0xff5b,0xff5c,
	0xff5d,0xff5e,0xffe0,0xffe1,0xffe2,0xffe3,0xffe4,0xffe5
	};

int16_t font_char_index(uint16_t ucode)
{
	uint16_t size = sizeof(zf_table_by_word);
	// 二分查找
	int16_t m = 0;
	uint16_t l = 0, r = size - 1;
	while(l <= r)
	{
		m = l + (r - l) / 2;
		uint16_t ch = pgm_read_byte(&zf_table_by_word[m]);
		if (ch > ucode)
		{
			r = m - 1;
		}
		else if (ch < ucode)
		{
			l = m + 1;
		}
		else
		{
			return m;
		}
	}
	return -1;
}

uint32_t font_addr_for_ucode_1516(uint16_t _Ucode)
{
	int32_t Address = -1;
    uint32_t BaseAdd = 0x0A76B8;
	uint32_t Ucode = _Ucode;

    if(Ucode >= 0x3400 && Ucode <= 0x4DB5) //UNICODE3.0 扩展汉字区 6582 个汉字
    {
		Address = (Ucode - 0x3400) * 32 + BaseAdd;
	}
    else if(Ucode >= 0x4E00 && Ucode <= 0x9FA5) //UNICODE3.0 字符区 20902 个汉字
	{
        Address = (Ucode - 0x4E00 + 6582) * 32 + BaseAdd;
	}
    else if((Ucode >= 0xFF00 && Ucode <= 0xFF5E) || (Ucode >= 0x20 && Ucode <= 0x7E))
    {
        if(Ucode == 0xFF00 || Ucode == 0x20) //空格
		{
            Address = (27484 + 538) * 32 + BaseAdd;
		}
        else if(Ucode > 0xFF00 && Ucode <= 0xFF5E)
		{
            Address = (Ucode - 0xFF00 + 27484 + 987) * 32 + BaseAdd;
		}
        else if(Ucode > 0x20 && Ucode <= 0x7E )
		{
            Address = (Ucode - 0x20 + 27484 + 987) * 32 + BaseAdd;
		}
    }
    else if ((Ucode >= 0x00A1 && Ucode <= 0x33D5 ) || (Ucode >= 0xE76C && Ucode <= 0xFFE5)) //字符区范围
	{
		int8_t zfindex = font_char_index(Ucode);
		if (zfindex != -1)
			Address = (uint8_t)zfindex * 32 + 27484 * 32 + BaseAdd;
	}
	if (Address == -1) {
		Address = font_addr_for_ucode_1516(0x20); // 例外
	}
	return Address;
}

uint32_t font_addr_for_ucode_1112(uint16_t _Ucode)
{
    int32_t Address = 0;
    uint32_t BaseAdd = 0x0000;
    uint32_t Ucode = _Ucode;

    if(Ucode >= 0x3400 && Ucode <= 0x4DB5) //UNICODE3.0 扩展汉字区 6582 个汉字
        Address = (Ucode - 0x3400) * 24 + BaseAdd;
    else if(Ucode >= 0x4E00 && Ucode <= 0x9FA5) //UNICODE3.0 字符区 20902 个汉字
        Address = (Ucode - 0x4E00 + 6582) * 24 + BaseAdd;
    else if((Ucode >= 0xFF00 && Ucode <= 0xFF5E) || (Ucode >= 0x20 && Ucode <= 0x7E) )
    {
        if(Ucode == 0xFF00 || Ucode == 0x20) //空格
            Address = (27484 + 538) * 24 + BaseAdd;
        else if(Ucode > 0xFF00 && Ucode <= 0xFF5E)
            Address = (Ucode - 0xFF00 + 27484 + 987) * 24 + BaseAdd;
        else if(Ucode > 0x20 && Ucode <= 0x7E )
            Address = (Ucode - 0x20 + 27484 + 987) * 24 + BaseAdd;
    }
    else if ((Ucode >= 0x00A1 && Ucode <= 0x33D5) || (Ucode >= 0xE76C && Ucode <= 0xFFE5)) //字符区范围
        Address = font_char_index(Ucode) * 24 + 27484 * 24 + BaseAdd;
	if (Address == -1) {
		Address = font_addr_for_ucode_1112(0x6211); // 例外
	}
	return Address;
}


uint32_t font_addr_for_ascii_57(uint8_t _ASCIICode)
{
    int32_t Address = 0;
    uint32_t BaseAdd = 0x188BD8;
    uint32_t ASCIICode = _ASCIICode;
	
	if (ASCIICode >= 0x20 && ASCIICode <= 0x7E)
		Address = (ASCIICode - 0x20) * 8 + BaseAdd;
	else
		return font_addr_for_ascii_57(0x20);
	return Address;
}

uint32_t font_addr_for_ascii_78(uint8_t _ASCIICode)
{
    int32_t Address = 0;
    uint32_t BaseAdd = 0x188ED8;
    uint32_t ASCIICode = _ASCIICode;
	
	if (ASCIICode >= 0x20 && ASCIICode <= 0x7E)
		Address = (ASCIICode - 0x20) * 8 + BaseAdd;
	else
		return font_addr_for_ascii_78(0x20);
	return Address;
}


#endif // __GT23L16U2W_ADDR_H_
